﻿namespace UnityEditor
{
    using NUnit.Framework;
    using System;
    using System.Collections.Generic;
    using UnityEngine;

    internal abstract class DefaultTreeViewDataSource : ITreeViewDataSource
    {
        protected TreeView.Node m_FakeNode;
        protected bool m_NeedRefreshVisibleFolders = true;
        protected bool m_RootIsCollapsable;
        protected TreeView.Node m_RootNode;
        protected bool m_ShowRootNode = true;
        protected TreeView m_TreeView;
        protected List<TreeView.Node> m_VisibleRows;

        public DefaultTreeViewDataSource(TreeView treeView)
        {
            this.m_TreeView = treeView;
        }

        public virtual bool CanBeMultiSelected(TreeView.Node node)
        {
            return true;
        }

        public virtual bool CanBeParent(TreeView.Node node)
        {
            return true;
        }

        public abstract void FetchData();
        public virtual TreeView.Node FindNodeByID(int instanceID)
        {
            return TreeView.Node.FindNodeRecursive(this.m_RootNode, instanceID);
        }

        public virtual int[] GetExpandedInstanceIDs()
        {
            return this.expandedInstanceIDs.ToArray();
        }

        private void GetVisibleNodesRecursive(TreeView.Node node, List<TreeView.Node> nodes)
        {
            if ((node != this.m_RootNode) || this.m_ShowRootNode)
            {
                nodes.Add(node);
            }
            if (this.IsExpanded(node))
            {
                foreach (TreeView.Node node2 in node.children)
                {
                    this.GetVisibleNodesRecursive(node2, nodes);
                }
            }
        }

        public virtual List<TreeView.Node> GetVisibleRows()
        {
            if ((this.m_VisibleRows == null) || this.m_NeedRefreshVisibleFolders)
            {
                this.m_VisibleRows = new List<TreeView.Node>();
                this.GetVisibleNodesRecursive(this.m_RootNode, this.m_VisibleRows);
                this.m_NeedRefreshVisibleFolders = false;
                this.m_TreeView.Repaint();
            }
            return this.m_VisibleRows;
        }

        public bool HasFakeNode()
        {
            return (this.m_FakeNode != null);
        }

        public virtual void InsertFakeNode(int instanceID, int parentInstanceID, string nodeDisplayName, Texture2D icon)
        {
            TreeView.Node node = this.FindNodeByID(instanceID);
            if (node != null)
            {
                Debug.LogError(string.Concat(new object[] { "Cannot insert fake node because instanceID is not unique ", instanceID, " node already there: ", node.displayName }));
            }
            else if (this.FindNodeByID(parentInstanceID) == null)
            {
                Debug.LogError("No parent node found");
            }
            else
            {
                TreeView.Node rootNode;
                this.SetExpandedByInstanceID(parentInstanceID, true);
                List<TreeView.Node> visibleRows = this.GetVisibleRows();
                int indexOfInstanceID = TreeView.GetIndexOfInstanceID(visibleRows, parentInstanceID);
                if (indexOfInstanceID >= 0)
                {
                    rootNode = visibleRows[indexOfInstanceID];
                }
                else
                {
                    rootNode = this.m_RootNode;
                }
                int depth = rootNode.depth + ((rootNode != this.m_RootNode) ? 1 : 0);
                this.m_FakeNode = new TreeView.Node(instanceID, depth, rootNode, nodeDisplayName);
                this.m_FakeNode.icon = icon;
                List<TreeView.Node> list2 = new List<TreeView.Node>(rootNode.children) {
                    this.m_FakeNode
                };
                list2.Sort(new SemiNumericDisplayNameListComparer());
                int num3 = parentInstanceID;
                int index = list2.IndexOf(this.m_FakeNode);
                if ((index != -1) && (index > 0))
                {
                    num3 = list2[index - 1].instanceID;
                }
                int num5 = TreeView.GetIndexOfInstanceID(visibleRows, num3);
                if (num5 < 0)
                {
                    if (visibleRows.Count > 0)
                    {
                        visibleRows.Insert(0, this.m_FakeNode);
                    }
                    else
                    {
                        visibleRows.Add(this.m_FakeNode);
                    }
                }
                else
                {
                    while (++num5 < visibleRows.Count)
                    {
                        if (visibleRows[num5].depth <= depth)
                        {
                            break;
                        }
                    }
                    if (num5 < visibleRows.Count)
                    {
                        visibleRows.Insert(num5, this.m_FakeNode);
                    }
                    else
                    {
                        visibleRows.Add(this.m_FakeNode);
                    }
                }
                this.m_NeedRefreshVisibleFolders = false;
                this.m_TreeView.Frame(this.m_FakeNode.instanceID, true, false);
                this.m_TreeView.Repaint();
            }
        }

        public virtual bool IsExpandable(TreeView.Node node)
        {
            return (node.children.Length > 0);
        }

        public virtual bool IsExpanded(TreeView.Node node)
        {
            return this.IsExpandedByInstanceID(node.instanceID);
        }

        public virtual bool IsExpandedByInstanceID(int instanceID)
        {
            return (this.expandedInstanceIDs.BinarySearch(instanceID) >= 0);
        }

        public virtual bool IsRenamingNodeAllowed(TreeView.Node node)
        {
            IHierarchyProperty property = new HierarchyProperty(HierarchyType.Assets);
            if (property.Find(node.instanceID, null) && !property.isMainRepresentation)
            {
                return false;
            }
            return (node.parent != null);
        }

        public void ReloadData()
        {
            this.m_FakeNode = null;
            this.FetchData();
        }

        public virtual void RemoveFakeNode()
        {
            if (this.HasFakeNode())
            {
                int instanceID = this.m_FakeNode.instanceID;
                List<TreeView.Node> visibleRows = this.GetVisibleRows();
                int indexOfInstanceID = TreeView.GetIndexOfInstanceID(visibleRows, instanceID);
                if (indexOfInstanceID != -1)
                {
                    visibleRows.RemoveAt(indexOfInstanceID);
                }
                this.m_FakeNode = null;
            }
        }

        public virtual void SetExpanded(TreeView.Node node, bool expand)
        {
            this.SetExpandedByInstanceID(node.instanceID, expand);
        }

        public virtual bool SetExpandedByInstanceID(int instanceID, bool expand)
        {
            bool flag = this.IsExpandedByInstanceID(instanceID);
            if (expand == flag)
            {
                return false;
            }
            if (expand)
            {
                Assert.That(!this.expandedInstanceIDs.Contains(instanceID));
                this.expandedInstanceIDs.Add(instanceID);
                this.expandedInstanceIDs.Sort();
            }
            else
            {
                this.expandedInstanceIDs.Remove(instanceID);
            }
            this.m_NeedRefreshVisibleFolders = true;
            return true;
        }

        public virtual void SetExpandedInstanceIDs(int[] instanceIDs)
        {
            this.expandedInstanceIDs = new List<int>(instanceIDs);
            this.expandedInstanceIDs.Sort();
            this.m_NeedRefreshVisibleFolders = true;
        }

        public virtual void SetExpandedWithChildren(TreeView.Node node, bool expand)
        {
            this.SetExpanded(node, expand);
            foreach (TreeView.Node node2 in node.children)
            {
                this.SetExpandedWithChildren(node2, expand);
            }
        }

        protected List<int> expandedInstanceIDs
        {
            get
            {
                return this.m_TreeView.m_State.m_ExpandedInstanceIDs;
            }
            set
            {
                this.m_TreeView.m_State.m_ExpandedInstanceIDs = value;
            }
        }

        internal class SemiNumericDisplayNameListComparer : IComparer<TreeView.Node>
        {
            public int Compare(TreeView.Node x, TreeView.Node y)
            {
                if (x == y)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
                return EditorUtility.SemiNumericCompare(x.displayName, y.displayName);
            }
        }
    }
}

